package main

import (
	"fmt"
	"reflect"
	"strconv"
)

type Human struct {
	name string
	age int
	phone string
}

type Student struct {
	Human //匿名字段Human
	school string
	loan float32
}

type Employee struct {
	Human //匿名字段Human
	company string
	money float32
}

// 定义interface
type Men interface {
	SayHi()
	Sing(lyrics string)
	Guzzle(beerStein string)
}
type YoungChap interface {
	SayHi()
	Sing(song string)
	BorrowMoney(amount float32)
}
type ElderlyGent interface {
	SayHi()
	Sing(song string)
	SpendSalary(amount float32)
}

// Human对象实现SayHi方法
func (h *Human) SayHi()  {
	fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)
}
// Human对象实现Sing方法
func (h *Human) Sing(lyrics string)  {
	fmt.Println("La la,la la la, la la la la la ...\n", lyrics)
}
//Human对象实现Guzzle方法
func (h *Human) Guzzle(beerStein string) {
	fmt.Println("Guzzle Guzzle Guzzle...", beerStein)
}
// Employee重载Human的SayHi方法
func (e *Employee) SayHi()  {
	fmt.Printf("Hi, I am %s, I work at %s. Call me on %s\n", e.name,
		e.company, e.phone)
}
// Student实现BorrowMoney
func (s * Student) BorrowMoney(amount float32)  {
	s.loan += amount
}
// Employee实现SpendSalary
func (e *Employee) SpendSalary(amount float32)  {
	e.money -= amount
}

func (s *Student) Strings()  {
	fmt.Printf("I am a student,I am %s,I am at %s have %.2f loan\n", s.name, s.school,s.loan)
}
func (e *Employee) Strings()  {
	fmt.Printf("I am an employee,I am %s,I am at %s have %.2f money\n", e.name, e.company, e.money)
}

// 任何实现了 String方法的类型都能作为参数被fmt.Println调用
func (h Human) String() string {
	return "❰"+h.name+" - "+strconv.Itoa(h.age) + " years - ✆ " + h.phone + "❱"
}

func main() {
	mar := Student{Human{"Mar",20,"222-111-213"},"Yz", 1000}
	kat := Employee{Human{"Kat", 29, "333-129-589"}, "Yba", 1200}

	mar.SayHi()
	mar.Strings()
	mar.BorrowMoney(100)
	mar.Strings()
	mar.Sing("hahaha")
	mar.Guzzle("cha")

	kat.SayHi()
	kat.String()
	kat.SpendSalary(120)
	kat.String()
	kat.Sing("gogog")
	kat.Guzzle("awo")

	fmt.Println("This Human is ", kat)

	// 定义a为空接口，相当于C的void*
	var a interface{}
	var i int = 5
	s := "Hello world"
	// a可以存储任意类型的数值
	a = i
	a = s
	fmt.Println("空interface可存储任意类型数值：", a)

	testElement()
	reflects()
}

// 通过element.() 获取类型  .() 获取类型

type Element interface {}
type List []Element
type Person struct {
	name string
	age int
}

// 定义String方法，实现fmt.Stringer
func (p Person) String() string  {
	return "(name: "+p.name+" - age: "+strconv.Itoa(p.age) + " years)"
}

func testElement() {
	list := make(List, 3)
	list[0] = 1
	list[1] = "Hello"
	list[2] = Person{"Denai", 20}

	for index, element := range list{
		if value,ok :=element.(int); ok {
			fmt.Printf("list[%d] is an int and its value is %d\n", index, value)
		} else if value,ok := element.(string); ok {
			fmt.Printf("list[%d] is a string and its value is %s\n", index, value)
		} else if value,ok := element.(Person); ok {
			fmt.Printf("list[%d] is a Person and its value is %s\n", index, value)
		}else{
			fmt.Printf("list[%d] is of a different type\n", index)
		}
	}

	switchs()
}

func switchs()  {
	list := make(List, 3)
	list[0] = 1
	list[1] = "Hello"
	list[2] = Person{"Denai", 20}

	fmt.Println("使用switch...")
	for index, element := range list{
		switch value :=element.(type) {   // element.(type) 语法只能在switch中使用
		case int:
			fmt.Printf("list[%d] is an int and its value is %d\n", index, value)
		case string:
			fmt.Printf("list[%d] is a string and its value is %s\n", index, value)
		case Person:
			fmt.Printf("list[%d] is a Person and its value is %s\n", index, value)
		default:
			fmt.Printf("list[%d] is of a different type\n", index)
		}
	}
}

// 反射
func reflects() {
	mark := Person{"Mark", 28}

	t := reflect.TypeOf(mark)
	v := reflect.ValueOf(mark)

	fmt.Printf("type:%v\nvalue:%v\n", t,v)

	var x float64 = 3.4
	xv := reflect.ValueOf(x)
	fmt.Println("type:", xv.Type())
	fmt.Println("kind is Person: ", xv.Kind() == reflect.Float64)
	fmt.Println("value:", xv.Float())

	p := reflect.ValueOf(&x) // 要修改需要通过&x
	xv2 := p.Elem()
	xv2.SetFloat(7.2)
	fmt.Println("value:", x)

}